package com.example.downloader.model;

import android.util.Log;

import java.util.Map;
import java.util.Set;

/**
 * Created by Administrator on 2017/9/22 0022.
 */

public class DownloadCallback<Result> implements IDownloadCallback<Result> {
    public static final int FLAG_FREE = 0x0 << 7;
    public static final int FLAG_READY = 0x01 << 7 | FLAG_FREE;
    public static final int FLAG_DOWNLOADING = 0x02 << 7 | FLAG_READY;
    public static final int FLAG_FINISHED = FLAG_DOWNLOADING | 0x64;//0x64 = 100表示下载100%完成
    public static final int FLAG_CANCLED = 0x04 << 7;
    public static final int FLAG_ERROR = 0x08 << 7;


    private static final int MASK_DOWNLOAD_PROGRESS = 0x7f;
    private static final int MASK_DOWNLOAD_STATE = FLAG_FREE | FLAG_READY | FLAG_DOWNLOADING;
    private static final int MASK_DOWNLOADING_PROGRESS_STATE = MASK_DOWNLOAD_STATE | MASK_DOWNLOAD_PROGRESS;
    private static final int MASK_DOWNLOAD_CANCLED = FLAG_CANCLED;
    private static final int MASK_DOWNLOAD_ERROR = FLAG_ERROR;


    private int mState;
    private ProgressAware mProgressAware;


    //    private HttpTask<File> mWorking;
    private Map<String, DownloadTask<Result>> mDownloadingWorkings;
    private Set<String> mSuccessedWorks;
    //    private final String mWorkingUri;
    private DownloadInfo mDownloadInfo;
    private String mDownloadPath;

    DownloadCallback(ProgressAware progressAware/*, HttpTask<File> working*/, Map<String, DownloadTask<Result>> downloadingWork, Set<String> successed, DownloadInfo downloadInfo, String downloadPath) {
        mProgressAware = progressAware;
        mDownloadingWorkings = downloadingWork;
        mSuccessedWorks = successed;
//        mWorkingUri = workingUri;
        mDownloadInfo = downloadInfo;
        mDownloadPath = downloadPath;
//        mWorking = working;
        mState = FLAG_FREE;
        mProgressAware.setFreeState(true);

    }

    public ProgressAware getProgressAware() {
        return mProgressAware;
    }

    public void setProgressAware(ProgressAware progressAware) {
        this.mProgressAware = progressAware;
        if (mProgressAware != null) {
            switch (getState()) {
                case FLAG_ERROR:
                    mProgressAware.setErrorState();
                    break;
                case FLAG_CANCLED:
                    mProgressAware.setCancledState();
                    break;
                case FLAG_DOWNLOADING:
                    mProgressAware.setDownloadingState(MASK_DOWNLOAD_PROGRESS & mState);
                    break;
                case FLAG_FINISHED:
                    mProgressAware.setDownloadingFinishedState(mDownloadInfo, mDownloadPath);
                    break;
                case FLAG_READY:
                    mProgressAware.setReadyState();
                    break;
                case FLAG_FREE:
                    mProgressAware.setFreeState(true);
                    break;
                default:
                    break;
            }
        }


    }

    @Override
    public void onStarted() {
        mState |= FLAG_DOWNLOADING;
        if (mProgressAware != null) {
            mProgressAware.setDownloadingState(0);
        }
        Log.i("@@", "@@onStarted");
    }

    @Override
    public void onSuccess(Result result) {
        mState &= ~MASK_DOWNLOAD_PROGRESS;
        mState |= FLAG_FINISHED;
        if (mProgressAware != null) {
            mProgressAware.setDownloadingFinishedState(mDownloadInfo, mDownloadPath);
        }
        mDownloadingWorkings.remove(mDownloadInfo.uri);
        mSuccessedWorks.add(mDownloadInfo.uri);
        releaseInternal(true);

        Log.i("@@", "@@onSuccess");
    }

    @Override
    public void onError() {
        mState |= FLAG_ERROR;
        if (mProgressAware != null) {
            mProgressAware.setErrorState();
        }
        releaseInternal(true);
        Log.i("@@", "@@onError");
    }

    @Override
    public void onCancelled() {
        mState |= FLAG_CANCLED;
        if (mProgressAware != null) {
            mProgressAware.setCancledState();
        }
        releaseInternal(true);
        Log.i("@@", "@@onCancelled");
    }

    @Override
    public void onWaiting() {
        mState |= FLAG_READY;
        if (mProgressAware != null) {
            mProgressAware.setReadyState();
        }
        Log.i("@@", "@@onWaiting");
    }

    @Override
    public void onLoading(int total, int current) {
        final int progress = (int) (((double) current) / total * 100);
        mState &= ~MASK_DOWNLOAD_PROGRESS;
        mState |= progress;
        if (mProgressAware != null) {
            mProgressAware.setDownloadingState(progress);
        }
        Log.i("@@", "@@onLoading:" + current + "/" + total);
    }

    public int getState() {
        if ((MASK_DOWNLOAD_ERROR & mState) == FLAG_ERROR) {
            return FLAG_ERROR;
        } else if ((MASK_DOWNLOAD_CANCLED & mState) == FLAG_CANCLED) {
            return FLAG_CANCLED;
        } else if ((mState & MASK_DOWNLOADING_PROGRESS_STATE) == FLAG_FINISHED) {
            return FLAG_FINISHED;
        } else {
            return mState & MASK_DOWNLOAD_STATE;
        }
    }

    void interruptUI() {
//        if (mWorking != null && !mWorking.isCancelled()) {
//            mWorking.cancel();
//        }
//        mWorking = null;
        mProgressAware = null;
    }

    private void releaseInternal(boolean exit) {
        mDownloadingWorkings = null;
        mSuccessedWorks = null;
        if (exit) {
            mDownloadInfo = null;
            mDownloadPath = null;
        }
    }


    DownloadCallback<Result> release() {
        mProgressAware = null;
        releaseInternal(true);
        mState = FLAG_FREE;
        return this;
    }


}
